package edu.zueb.sport.rest;

import static edu.zueb.sport.rest.BorrowRestController.PATH_BORROW;

import edu.zueb.sport.dao.BorrowMapper;
import edu.zueb.sport.dao.EquipmentMapper;
import edu.zueb.sport.entity.Borrow;
import edu.zueb.sport.entity.User;
import edu.zueb.sport.enums.BorrowStatusEnum;
import edu.zueb.sport.exception.RestException;
import edu.zueb.sport.rest.api.*;
import edu.zueb.sport.utils.JsonUtils;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@Tag(name = "出借管理", description = "出借管理")
@Slf4j
@RestController
@RequestMapping(PATH_BORROW)
public class BorrowRestController {

    public static final String PATH_BORROW = "/api/borrow";

    @Autowired
    BorrowMapper borrowMapper;

    @Autowired
    EquipmentMapper equipmentMapper;

    @PostMapping("/apply")
    public RestResponse<Borrow> apply(@RequestBody BorrowDTO borrowDTO, HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        User user = AuthRestController.TOKEN_CACHE.getIfPresent(token);
        if (user == null) {
            return RestResponse.fail("用户未登录");
        }
        // 默认状态为待审批
        Borrow borrow = new Borrow();
        borrow.setEquipmentId(borrowDTO.getEquipmentId());
        borrow.setBorrowQuantity(borrowDTO.getBorrowQuantity());
        try {
            Date preReturnTime = DateUtils.parseDate(borrowDTO.getPreReturnTime(), "yyyy-MM-dd'T'HH:mm:ss.SSSX");
            borrow.setPreReturnTime(preReturnTime);
        } catch (ParseException e) {
            log.error("parse date error", e);
            throw new RestException("计划归还时间有误");
        }
        borrow.setUserId(user.getUserId());
        borrow.setBorrowStatus(BorrowStatusEnum.PENDING.getValue());
        borrowMapper.insertBorrow(borrow);
        return RestResponse.success(borrow);
    }

    @PostMapping("/approve")
    public RestResponse<Borrow> approveBorrow(@RequestBody Borrow borrow) {
        // 特别注意：这个方法理论上是要加事务的
        Integer borrowId = borrow.getBorrowId();
        Borrow borrowInfo = borrowMapper.getBorrowById(borrowId);
        if (borrowInfo == null) {
            throw new RestException("审批失败");
        }
        Integer borrowQuantity = borrowInfo.getBorrowQuantity();
        int row = equipmentMapper.subtractStockQuantity(borrowInfo.getEquipmentId(), borrowQuantity);
        if (row != 1) {
            throw new RestException("库存不足");
        }
        // 批准状态
        borrow.setBorrowStatus(BorrowStatusEnum.APPROVED.getValue());
        int rows = borrowMapper.updateBorrow(borrow);
        if (rows != 1) {
            throw new RestException("审批失败");
        }
        return RestResponse.success(borrow);
    }

    @PostMapping("/reject")
    public RestResponse<Borrow> rejectBorrow(@RequestBody Borrow borrow) {
        // 拒绝状态
        borrow.setBorrowStatus(BorrowStatusEnum.REJECTED.getValue());
        int rows = borrowMapper.updateBorrow(borrow);
        if (rows != 1) {
            throw new RestException("拒绝失败");
        }
        return RestResponse.success(borrow);
    }

    @PostMapping("/return")
    public RestResponse<Borrow> returnBorrow(@RequestBody Borrow borrow) {
        // 特别注意：这个方法理论上是要加事务的
        Integer borrowId = borrow.getBorrowId();
        Borrow borrowInfo = borrowMapper.getBorrowById(borrowId);
        if (borrowInfo == null) {
            throw new RestException("审批失败");
        }
        Integer borrowQuantity = borrowInfo.getBorrowQuantity();
        // 还原库存，负负得正
        int row = equipmentMapper.subtractStockQuantity(borrowInfo.getEquipmentId(), -borrowQuantity);
        if (row != 1) {
            throw new RestException("入库失败");
        }
        // 归还状态
        borrow.setBorrowStatus(BorrowStatusEnum.RETURNED.getValue());
        int rows = borrowMapper.updateBorrow(borrow);
        if (rows != 1) {
            throw new RestException("拒绝失败");
        }
        return RestResponse.success(borrow);
    }

    @PostMapping(value = "/list")
    public RestResponse<Page<BorrowVO>> list(
            @RequestParam(value = "equipmentTypeId", required = false) Integer equipmentTypeId,
            @RequestParam(value = "userId", required = false) Integer userId,
            @RequestParam(value = "username", required = false) String username,
            @RequestParam(value = "userRealName", required = false) String userRealName,
            @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        log.info("username={}|userRealName={}|pageNo={}|pageSize={}", username, userRealName, pageNo, pageSize);
        int totalCount = borrowMapper.countByPage(equipmentTypeId, userId, username, userRealName);
        log.info("totalCount={}", totalCount);
        if (totalCount == 0) {
            return RestResponse.success(Page.empty());
        }
        List<BorrowVO> borrowVOS =
                borrowMapper.listByPage(equipmentTypeId, userId, username, userRealName, pageNo, pageSize);
        return RestResponse.success(Page.asPage(totalCount, pageSize, borrowVOS));
    }

    @PostMapping(value = "/myBorrows")
    public RestResponse<Page<BorrowVO>> myBorrows(
            @RequestParam(value = "equipmentTypeId", required = false) Integer equipmentTypeId,
            @RequestParam(value = "userId", required = false) Integer userId,
            @RequestParam(value = "username", required = false) String username,
            @RequestParam(value = "userRealName", required = false) String userRealName,
            @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
            HttpServletRequest request) {
        // 这里可以用 HttpHolder 来获取，避免每次这样，懒得改了
        String token = request.getHeader("Authorization");
        User user = AuthRestController.TOKEN_CACHE.getIfPresent(token);
        if (user == null) {
            return RestResponse.fail("用户未登录");
        }
        log.info("user={}", JsonUtils.toJson(user));
        userId = user.getUserId();
        log.info("username={}|userRealName={}|pageNo={}|pageSize={}", username, userRealName, pageNo, pageSize);
        int totalCount = borrowMapper.countByPage(equipmentTypeId, userId, username, userRealName);
        log.info("totalCount={}", totalCount);
        if (totalCount == 0) {
            return RestResponse.success(Page.empty());
        }
        List<BorrowVO> borrowVOS =
                borrowMapper.listByPage(equipmentTypeId, userId, username, userRealName, pageNo, pageSize);
        return RestResponse.success(Page.asPage(totalCount, pageSize, borrowVOS));
    }
}
